<template>
  <panel title="进程">
    <div class="content">
      <div class="text-center">
        <p class="font-bold">运行时间</p>
        <p v-text="uptime" />
      </div>
      <div class="text-center">
        <p class="font-bold">进程CPU使用率</p>
        <p v-text="isNaN(processCpuLoad) ? '-' : `${(processCpuLoad * 100).toFixed(2)}%`" />
      </div>
      <div class="text-center">
        <p class="font-bold">系统CPU使用率</p>
        <p v-text="isNaN(systemCpuLoad) ? '-' : `${(systemCpuLoad * 100).toFixed(2)}%`" />
      </div>
      <div class="text-center">
        <p class="font-bold">CPU核心数</p>
        <p v-text="systemCpuCount" />
      </div>
    </div>
  </panel>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
import panel from './panel.vue';
import api from "@/http/api";
import moment from "moment";

const uptime = ref(null);
const systemCpuLoad = ref(null);
const processCpuLoad = ref(null);
const systemCpuCount = ref(null);

const fetchMetric = async (name) => {
  const res = await api.get('/actuator/metrics/' + name);
  return res.data;
};

const fetchUptime = async() => {
  try {
    const res = await fetchMetric('process.uptime');
    const duration = moment.duration(toMillis(res.measurements[0].value, res.baseUnit));
    uptime.value = `${Math.floor(
      duration.asDays(),
    )}d ${duration.hours()}h ${duration.minutes()}m ${duration.seconds()}s`;
  } catch (err) {
    console.warn('Fetching Uptime failed:', err);
  }
};

const fetchCpuCount = async() => {
  try {
    const res = await fetchMetric('system.cpu.count');
    systemCpuCount.value = res.measurements[0].value;
  } catch (err) {
    console.warn('Fetching Cpu Count failed:', err);
  }
};

const fetchCpuLoadMetrics = async() => {
  try {
    const res = await fetchMetric('process.cpu.usage');
    processCpuLoad.value = res.measurements[0].value;
  } catch (err) {
    console.warn('Fetching Process CPU Load failed:', err);
  }

  try {
    const res = await fetchMetric('system.cpu.usage');
    systemCpuLoad.value = res.measurements[0].value;
  } catch (err) {
    console.warn('Fetching System CPU Load failed:', err);
  }
};

const toMillis = (value, baseUnit) => {
  switch (baseUnit) {
    case 'nanoseconds':
      return value / 1000000;
    case 'microseconds':
      return value / 1000;
    case 'milliseconds':
      return value;
    case 'seconds':
    default:
      return value * 1000;
  }
};

const fetchInfo = async() => {
  await fetchUptime();
  await fetchCpuCount();
  await fetchCpuLoadMetrics();
};

const shutdown = ref(false);
const loopWithDelay = async(taskFn, interval = 1000) => {
  while (!shutdown.value) {
    await taskFn();
    await new Promise(res => setTimeout(res, interval));
  }
}

onMounted(() => {
  loopWithDelay(fetchInfo);
});

onUnmounted(() => {
  shutdown.value = true;
});
</script>

<style scoped>
.content {
  display: flex;
  flex-direction: row;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
  .text-center {
    text-align: center;
    flex-grow: 1;
  }
  .font-bold {
    margin-bottom: 5px;
  }
}
</style>